#include <stdio.h>
#include "util.h"
#include "symbol.h"
#include "types.h"
#include "irr/temp.h"
#include "irr/tree.h"
#include "irr/frame.h"
#include "irr/translate.h"
#include "env.h"

E_enventry E_VarEntry(Tr_access access, Ty_ty ty){
  E_enventry envEntry = checked_malloc(sizeof(*envEntry));
  envEntry->kind = E_varEntry;
  envEntry->u.var.access = access;
  envEntry->u.var.ty = ty;
  return envEntry;
}
E_enventry E_FunEntry(Tr_level level, Ty_tyList formals, Ty_ty result){
  E_enventry envEntry = checked_malloc(sizeof(*envEntry));
  envEntry->kind = E_funEntry;
  envEntry->u.fun.level = level;
  envEntry->u.fun.formals = formals;
  envEntry->u.fun.result = result;
  return envEntry;  
}

S_table E_base_tenv(void){
  S_table table = S_empty();
  S_enter(table, S_Symbol("int"), Ty_Int());
  S_enter(table, S_Symbol("string"), Ty_String());
  S_enter(table, S_Symbol("void"), Ty_Void());
  S_enter(table, S_Symbol("nil"), Ty_Nil());
  return table;
}
S_table E_base_venv(void){
  S_table table = S_empty();
  
  Ty_tyList endOfList = NULL;
  
  // HERE!!! ending representation
  
  // print
  Ty_tyList printList = Ty_TyList(Ty_String(), endOfList);
  S_enter(table, 
          S_Symbol("print"), 
          E_FunEntry(NULL, printList, Ty_Void()));
  
  // flush
  S_enter(table,
          S_Symbol("flush"),
          E_FunEntry(NULL, endOfList, Ty_Void()));
  
  // getchar() : string
  S_enter(table,
          S_Symbol("getchar"),
          E_FunEntry(NULL, endOfList, Ty_String()));
  
  // ord(s: string) : int
  S_enter(table,
          S_Symbol("ord"),
          E_FunEntry(NULL, Ty_TyList(Ty_String(), endOfList), 
                     Ty_Int()));
  
  // chr(i: int) : string
  S_enter(table,
          S_Symbol("chr"),
          E_FunEntry(NULL, Ty_TyList(Ty_Int(), endOfList), 
                     Ty_String()));
  
  // size(s: string) : int
  S_enter(table,
          S_Symbol("size"),
          E_FunEntry(NULL, Ty_TyList(Ty_String(), endOfList), 
                     Ty_Int()));
  
  // substring(s:string, first:int, n:int) : string
  Ty_tyList substringList = Ty_TyList(Ty_String(), 
                                      Ty_TyList(Ty_Int(),
                                                Ty_TyList(Ty_Int(),
                                                          endOfList)));
  S_enter(table,
          S_Symbol("substring"),
          E_FunEntry(NULL, substringList, 
                     Ty_Int()));
  
  // concat(s1: string, s2: string) : string
  Ty_tyList concatList = Ty_TyList(Ty_String(), 
                                   Ty_TyList(Ty_String(),
                                             endOfList));
  S_enter(table,
          S_Symbol("concat"),
          E_FunEntry(NULL, concatList, 
                     Ty_Int()));  
  // not(i: int) : int
  S_enter(table,
          S_Symbol("not"),
          E_FunEntry(NULL, Ty_TyList(Ty_Int(), endOfList), 
                     Ty_Int()));
  
  // exit(i: int)int
  S_enter(table,
          S_Symbol("exit"),
          E_FunEntry(NULL, Ty_TyList(Ty_Int(), endOfList), 
                     Ty_Void()));
  
  
  return table;
}